﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using Castle.Services.Transaction;
using Meqs.Entity;
using Meqs.Entity.Parameters;
using Meqs.Logic.Interface;

namespace Meqs.Logic.Implement
{
    [Transactional]
    public class MoralitySubmitRecordLogic : CommonLogic<MoralitySubmitRecord, int>, IMoralitySubmitRecordLogic
    {
        private ISchoolInfoLogic _schoolLogic;
        private IMoralityEvalListLogic _melLogic;
        private IMoralityDetailLogic _mdLogic;
        private IMoralityRemarkLogic _mrLogic;
        private IMoralityHistoryLogic _mhLogic;
        private IMoralityPersonCatchLogic _mpcLogic;
        private IMoralityPersonTypeCatchLogic _mptcLogic;
        private IMoralityPersonItemCatchLogic _mpicLogic;
        private IMoralityItemLogic _miLogic;
        public MoralitySubmitRecordLogic(ISchoolInfoLogic schoolLogic,
                                        IMoralityEvalListLogic melLogic,
                                        IMoralityDetailLogic mdLogic,
                                        IMoralityRemarkLogic mrLogic,
                                        IMoralityHistoryLogic mhLogic,
                                        IMoralityPersonCatchLogic mpcLogic,
                                        IMoralityPersonTypeCatchLogic mptcLogic,
                                        IMoralityPersonItemCatchLogic mpicLogic,
                                        IMoralityItemLogic miLogic)
        {
            _schoolLogic = schoolLogic;
            _melLogic = melLogic;
            _mdLogic = mdLogic;
            _mrLogic = mrLogic;
            _mhLogic = mhLogic;
            _mpcLogic = mpcLogic;
            _mptcLogic = mptcLogic;
            _mpicLogic = mpicLogic;
            _miLogic = miLogic;
        }
        #region Implementation of ICommonLogic<MoralitySubmitRecord, int>

        /// <sammury>
        /// 创建对象
        /// </sammury>
        /// <param name="entity"></param>
        /// <returns></returns>
        public int Create(MoralitySubmitRecord entity)
        {
            return CreateObject(entity);
        }

        /// <sammury>
        /// 更新对象
        /// </sammury>
        /// <param name="entity"></param>
        /// <returns></returns>
        public int Update(MoralitySubmitRecord entity)
        {
            return UpdateObject(entity);
        }

        /// <summary>
        /// 删除对象
        /// </summary>
        /// <param name="entityId"></param>
        /// <returns></returns>
        public int Delete(int entityId)
        {
            return DeleteObject(entityId);
        }

        /// <summary>
        /// 删除所有对象
        /// </summary>
        /// <returns></returns>
        public int DeleteAll()
        {
            return DeleteAllObject();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="entityId"></param>
        /// <returns></returns>
        public MoralitySubmitRecord FindById(int entityId)
        {
            return FindObjectById(entityId);
        }

        /// <summary>
        /// 检索对象数量
        /// </summary>
        /// <returns></returns>
        public int FindCount()
        {
            return FindObjectByCount();
        }

        /// <sammury>
        /// 检索对象
        /// </sammury>
        public IList<MoralitySubmitRecord> FindAll()
        {
            return FindAllObject();
        }

        /// <summary>
        /// 检索对象数量
        /// </summary>
        /// <returns></returns>
        public int FindCount(Hashtable table)
        {
            return FindObjectByCount(table);
        }

        /// <sammury>
        /// 检索对象
        /// </sammury>
        public IList<MoralitySubmitRecord> FindAll(Hashtable table)
        {
            return FindObject(table);
        }

        #endregion

        /// <summary>
        /// 获取德育评价提交记录
        /// </summary>
        /// <param name="clsID"></param>
        /// <param name="reportType"></param>
        /// <param name="year"></param>
        /// <param name="month"></param>
        /// <param name="schoolYear"></param>
        /// <param name="term"></param>
        /// <param name="schoolMark"></param>
        /// <returns></returns>
        public MoralitySubmitRecord GetRecordByCls(int clsID, int reportType, int year, int month,int day, int? schoolYear, int? term, string schoolMark)
        {
            try
            {
                Hashtable ht = new Hashtable();
                ht.Add("SchoolMark", schoolMark);
                ht.Add("ClsID", clsID);
                if (day==0)
                    ht.Add("ReportDate", new DateTime(year, month, 1));
                else
                    ht.Add("ReportDate", new DateTime(year, month, day));
                ht.Add("ReportType", reportType);
                ht.Add("SchoolYear", schoolYear);
                ht.Add("Term", term);
                return FindCustomerByID<MoralitySubmitRecord>("MoralitySubmitRecord.GetRecordByCls", ht);
            }
            catch (Exception)
            {
                return null;
            }
        }

        /// <summary>
        /// 保存记录
        /// </summary>
        /// <param name="list"></param>
        /// <param name="clsID"></param>
        /// <param name="reportType"></param>
        /// <param name="year"></param>
        /// <param name="month"></param>
        /// <param name="schoolYear"></param>
        /// <param name="term"></param>
        /// <param name="teacherID"></param>
        /// <param name="schoolMark"></param>
        /// <returns></returns>
        [Transaction(TransactionMode.Supported)]
        public bool SaveOrUpdateRecord(IList<Items> list, int clsID, int reportType, int year, int month,int day, int? schoolYear, int? term, int teacherID, string schoolMark)
        {
            try
            {
                if (schoolYear == null || term == null)
                {
                    SchoolInfo school = _schoolLogic.FindBySchoolMark(schoolMark);
                    schoolYear = school.SchoolYear;
                    term = school.SchoolTerm;
                }
                MoralityEvalList mel = _melLogic.GetEvalList(reportType, year, month, day, schoolYear, term, schoolMark);
                MoralitySubmitRecord msr = GetRecordByCls(clsID, reportType, year, month,day, schoolYear, term, schoolMark);
                MoralityHistory mh = _mhLogic.GetHistoryRecordByTerm((int) schoolYear, (int) term, schoolMark);
                
                // 如果德育评价记录为空，则插入一条记录
                if (mel == null)
                {
                    mel = new MoralityEvalList();
                    mel.HistoryID = mh.RID;
                    if (day==0)
                        mel.StartTime = new DateTime(year, month, 1);
                    else
                        mel.StartTime = new DateTime(year, month, day);
                    mel.Attribute = 3;

                    int melID = _melLogic.InsertMoralityEvalList(mel, schoolMark);
                    mel.RID = melID;
                }

                // 如果德育评价提交记录为空，则插入一条记录
                if (msr == null)
                {
                    msr = new MoralitySubmitRecord();
                    msr.ClassID = clsID;
                    msr.ListID = mel.RID;
                    msr.ManagerID = teacherID;
                    msr.Status = 1;
                    msr.Daily = DateTime.Now;
                    int msrID = InsertMoralitySubmitRecord(msr, schoolMark);
                    msr.RID = msrID;
                }

                // 清空该班的评价和备注
                DeleteAllRecord(msr.RID, schoolMark);
                IList<int> studentIDList = new List<int>();

                if (list == null) return true;
                Dictionary<int, double> dicMpc = new Dictionary<int, double>();
                Dictionary<DicKey, double> dicMptc = new Dictionary<DicKey, double>();
                Dictionary<DicKey, double[]> dicMpic = new Dictionary<DicKey, double[]>();
                // 保存评价和备注
                foreach (Items item in list)
                {
                    if (!string.IsNullOrEmpty(item.Remark))
                    {
                        MoralityRemark mr = new MoralityRemark();
                        mr.RecordID = msr.RID;
                        mr.StudentID = item.StudentID;
                        mr.Data = item.Remark;
                        _mrLogic.InsertMoralityRemark(mr, schoolMark);
                    }
                    if (item.StuItems != null && item.StuItems.Count > 0)
                    {
                        foreach (StuItems stuItem in item.StuItems)
                        {
                            MoralityDetail md = new MoralityDetail();
                            md.Itemid = stuItem.MoralityItemID;
                            md.RecordID = msr.RID;
                            md.StudentID = item.StudentID;
                            md.Param = stuItem.Param;

                            _mdLogic.InsertMoralityDetail(md, schoolMark);
                            if (!studentIDList.Contains((int)md.StudentID)) studentIDList.Add((int)md.StudentID);


                            #region 计算每套题目的总分

                            if (dicMpc.ContainsKey((int)md.StudentID))
                            //if (ContainsKey(dicMpc, (int)md.StudentID))
                            {
                                double allScore = dicMpc[(int)md.StudentID];
                                allScore += stuItem.Type == 1 ? stuItem.Param : stuItem.Param * stuItem.Score * stuItem.Operator;
                                dicMpc[(int)md.StudentID] = allScore;
                            }
                            else
                            {
                                dicMpc[(int)md.StudentID] = stuItem.Type == 1 ? stuItem.Param : stuItem.Param * stuItem.Score * stuItem.Operator;
                            }

                            #endregion

                            MoralityItem mi = _miLogic.GetItemByID(schoolMark, (int)md.Itemid);
                            #region 计算每道大题的分数

                            DicKey mptcKey = new DicKey( (int)md.StudentID, (int) mi.TypeID );
                            if (dicMptc.ContainsKey(mptcKey))
                            //if (ContainsKey(dicMptc, mptcKey))
                            {
                                double allScore = dicMptc[mptcKey];
                                allScore += stuItem.Type == 1 ? stuItem.Param : stuItem.Param * stuItem.Score * stuItem.Operator;
                                dicMptc[mptcKey] = allScore;
                            }
                            else
                            {
                                dicMptc[mptcKey] = stuItem.Type == 1 ? stuItem.Param : stuItem.Param * stuItem.Score * stuItem.Operator;
                            }

                            #endregion

                            #region 计算每道小题的分数

                            DicKey mpicKey = new DicKey( (int)md.StudentID, mi.RID );
                            if (dicMpic.ContainsKey(mpicKey))
                            //if (ContainsKey(dicMpic, mpicKey))
                            {
                                double allScore = dicMpic[mpicKey][0];
                                double allParam = dicMpic[mpicKey][1];
                                allScore += stuItem.Type == 1 ? stuItem.Param : stuItem.Param * stuItem.Score * stuItem.Operator;
                                allParam += stuItem.Param;
                                dicMpic[mpicKey] = new double[] { allScore, allParam };
                            }
                            else
                            {
                                double allScore = stuItem.Type == 1 ? stuItem.Param : stuItem.Param * stuItem.Score * stuItem.Operator;
                                double allParam = stuItem.Param;
                                dicMpic[mpicKey] = new double[] { allScore, allParam };
                            }

                            #endregion
                        }
                    }
                }

                foreach (int studentID in studentIDList)
                {
                    // 计算缓存表

                    // 1. 将结果汇总到每张单据中每个人的总分(表:MoralityPersonCatch)
                    int recordID = msr.RID;
                    // 先删除
                    _mpcLogic.DeleteMoralityPersonCatch(studentID, recordID, schoolMark);
                    // 再插入
                    MoralityPersonCatch mpc = new MoralityPersonCatch();
                    mpc.RecordID = recordID;
                    mpc.StudentID = studentID;
                    double score = dicMpc[studentID];
                    mpc.Score = score;
                    mpc.Dirty = 0;
                    _mpcLogic.InsertMoralityPersonCatch(mpc, schoolMark);

                    // 2. 将结果汇总到每张单据中每道大题每个人的得分(表:MoralityPersonTypeCatch)
                    _mptcLogic.DeleteMoralityPersonTypeCatch(studentID, recordID, schoolMark);
                    foreach (KeyValuePair<DicKey, double> dictionary in dicMptc)
                    {
                        if (dictionary.Key.StudentID != studentID) continue;
                        MoralityPersonTypeCatch mptc = new MoralityPersonTypeCatch();
                        mptc.Dirty = 0;
                        mptc.RecordID = recordID;
                        mptc.Score = dictionary.Value;
                        mptc.StudentID = studentID;
                        mptc.TypeID = dictionary.Key.ItemID;
                        _mptcLogic.InsertMoralityPersonTypeCatch(mptc, schoolMark);
                    }

                    // 3. 将结果汇总到每张单据中每道小题每个人的得分(表:MoralityPersonItemCatch)
                    _mpicLogic.DeleteMoralityPersonItemCatch(studentID, recordID, schoolMark);
                    foreach (KeyValuePair<DicKey, double[]> dictionary in dicMpic)
                    {
                        if (dictionary.Key.StudentID != studentID) continue;
                        MoralityPersonItemCatch mpic = new MoralityPersonItemCatch();
                        mpic.Dirty = 0;
                        mpic.ItemID = dictionary.Key.ItemID;
                        mpic.Param = dictionary.Value[1];
                        mpic.RecordID = recordID;
                        mpic.Score = dictionary.Value[0];
                        mpic.StudentID = studentID;
                        _mpicLogic.InsertMoralityPersonItemCatch(mpic, schoolMark);
                    }
                }

                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }
        [Transaction(TransactionMode.Supported)]
        public bool SaveOrUpdateRecordEx(int[] stuid, double[] scores, int clsID, int reportType, int year, int month, int day, int? schoolYear, int? term, int teacherID, string schoolMark)
        {
            try
            {
                if (schoolYear == null || term == null)
                {
                    SchoolInfo school = _schoolLogic.FindBySchoolMark(schoolMark);
                    schoolYear = school.SchoolYear;
                    term = school.SchoolTerm;
                }
                MoralityEvalList mel = _melLogic.GetEvalList(reportType, year, month, day, schoolYear, term, schoolMark);
                MoralitySubmitRecord msr = GetRecordByCls(clsID, reportType, year, month, day, schoolYear, term, schoolMark);
                MoralityHistory mh = _mhLogic.GetHistoryRecordByTerm((int)schoolYear, (int)term, schoolMark);

                // 如果德育评价记录为空，则插入一条记录
                if (mel == null)
                {
                    mel = new MoralityEvalList();
                    mel.HistoryID = mh.RID;
                    if (day == 0)
                        mel.StartTime = new DateTime(year, month, 1);
                    else
                        mel.StartTime = new DateTime(year, month, day);
                    mel.Attribute = 3;

                    int melID = _melLogic.InsertMoralityEvalList(mel, schoolMark);
                    mel.RID = melID;
                }

                // 如果德育评价提交记录为空，则插入一条记录
                if (msr == null)
                {
                    msr = new MoralitySubmitRecord();
                    msr.ClassID = clsID;
                    msr.ListID = mel.RID;
                    msr.ManagerID = teacherID;
                    msr.Status = 1;
                    msr.Daily = DateTime.Now;
                    int msrID = InsertMoralitySubmitRecord(msr, schoolMark);
                    msr.RID = msrID;
                }


                for (int i = 0; i < stuid.Length; i++) {

                    // 1. 将结果汇总到每张单据中每个人的总分(表:MoralityPersonCatch)
                    int recordID = msr.RID;
                    // 先删除
                    _mpcLogic.DeleteMoralityPersonCatch(stuid[i], recordID, schoolMark);
                    // 再插入
                    MoralityPersonCatch mpc = new MoralityPersonCatch();
                    mpc.RecordID = recordID;
                    mpc.StudentID = stuid[i];
                    double score = scores[i];
                    mpc.Score = score;
                    mpc.Dirty = 0;
                    _mpcLogic.InsertMoralityPersonCatch(mpc, schoolMark);

                }


                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }
        /// <summary>
        /// 保存
        /// </summary>
        /// <param name="moralitySubmitRecord"></param>
        /// <param name="schoolMark"></param>
        /// <returns></returns>
        public int InsertMoralitySubmitRecord(MoralitySubmitRecord moralitySubmitRecord, string schoolMark)
        {
            Hashtable ht = new Hashtable();
            ht.Add("MoralitySubmitRecord", moralitySubmitRecord);
            ht.Add("SchoolMark", schoolMark);
            return (int)InsertCustomer("MoralitySubmitRecord.InsertMoralitySubmitRecord", ht);
        }

        /// <summary>
        /// 清空记录
        /// </summary>
        /// <param name="recordID"></param>
        /// <param name="schoolMark"></param>
        /// <returns></returns>
        public int DeleteAllRecord(int recordID, string schoolMark)
        {
            Hashtable ht = new Hashtable();
            ht.Add("RecordID", recordID);
            ht.Add("SchoolMark", schoolMark);
            return DeleteCustomer("MoralitySubmitRecord.DeleteAllRecord", ht);
        }

        private static bool ContainsKey<TKey, TValue>(Dictionary<TKey, TValue> dic, TKey key)
        {
            foreach (KeyValuePair<TKey, TValue> pair in dic)
            {
                if (pair.Key.Equals(key)) return true;
            }
            return false;
        }
    }

    internal class DicKey
    {
        public DicKey()
        {
        }

        private int _studentID;
        private int _itemID;

        public DicKey(int studentID, int itemID)
        {
            _studentID = studentID;
            _itemID = itemID;
        }

        public int StudentID
        {
            get { return _studentID; }
            set { _studentID = value; }
        }

        public int ItemID
        {
            get { return _itemID; }
            set { _itemID = value; }
        }

        public bool Equals(DicKey other)
        {
            if (ReferenceEquals(null, other)) return false;
            if (ReferenceEquals(this, other)) return true;
            return other._studentID == _studentID && other._itemID == _itemID;
        }

        public override bool Equals(object obj)
        {
            if (ReferenceEquals(null, obj)) return false;
            if (ReferenceEquals(this, obj)) return true;
            if (obj.GetType() != typeof(DicKey)) return false;
            return Equals((DicKey)obj);
        }

        public override int GetHashCode()
        {
            unchecked
            {
                return (_studentID * 397) ^ _itemID;
            }
        }
    }
}